.. This file was automatically converted from MediaWiki syntax. If some markup is wrong, looks weird or doesn't make sense, feel free to fix it. Please remove this comment once this file was manually checked and no "strange ReST" artifacts remain. .. _particle-effects: Particle Effects ================ .. only:: python Particle effects involve the use of several small images acting on the same set of forces. These particles are created, they move, and they die out. These systems are dynamic and may be used for such effects as explosions, smoke, bubbling liquid and swarms. In essence, any particle effect needs three key parts: the renderer, the emitter, and the factory. The renderer translates the particle object into a visible object on the screen. The emitter assigns initial locations and velocity vectors for the particles. The factory generates particles and assigns their attributes. There are many different types of each part, and they each have their own parameters. Creating your own particle effects using code alone may be difficult. A particle effect panel is available to ease through this process. This section will discuss using the particle panel and the large number of variables associated with particle effects. .. only:: cxx Fire,  smoke, glowing, explosion, water fountain, falling leaves, fur, hair and many other fuzzy effects are created procedurally using particle systems. It's important not to make the assumption that particles must have the size of a 'particle' that is very small, particles can have any size and any mass. Particles are physical entities which inherit PhysicsObject. Panda3D provides a tool which simplifies testing particle systems. The tool is called (Particle Panel) and is written in python. The link to run the particle panel is in the same folder as the particle sample which comes with Panda3D. A particle system in Panda3D consists of 6 components: ====================================================== #. Factory #. Emitter #. Physics engine #. Renderer #. Particle System Controller (Particle System) #. Particle System Manager (Optional) Factory: ======== Particles are generated in this stage using the provided parameters. Panda3D Provides 2 Factories: - PointParticleFactory: Generates particles with default rotation. - ZspintParticleFactory:  [From Source Code] Generates particles which spin along their z-axis. this is kind of an intermediary class- if you're using a SpriteParticleRenderer and you want your sprites to spin without having them be full-blown oriented (i.e. angry quat math), use this. Note:  'set\_final\_angle' and 'angular\_velocity' are mutually exclusive APIs  if angular-velocity is specified, final\_angle is ignored. [Sample] .. code-block:: cpp PT(PointParticleFactory) pt_particle_factory = new PointParticleFactory(); pt_particle_factory->set_lifespan_base(0.5); pt_particle_factory->set_lifespan_spread(0); pt_particle_factory->set_mass_base(1.0); pt_particle_factory->set_mass_spread(0); pt_particle_factory->set_terminal_velocity_base(400); pt_particle_factory->set_terminal_velocity_spread(0); Emitter: ======== The emitter is used to emit the particles generated by the factory. The shape of the emitter determins the initial position and motion direction of the particles. Available Emitters: =================== - ArcEmitter -  BoxEmitter -  DiscEmitter -  LineEmitter -  RectangleEmitter -  RingEmitter -  SphereSurfaceEmitter -  SphereVolumeEmitter -  TangentRingEmitter Each emitter is declared in a separate .h file with the same name as the emitter. For example: ArcEmitter is declared in arcEmitter.h [Sample] .. code-block:: cpp PT(SphereVolumeEmitter) sphere_emitter = new SphereVolumeEmitter; sphere_emitter->set_emission_type(SphereVolumeEmitter::ET_RADIATE); sphere_emitter->set_radius(3.0); // negative values emit the particles toward the sphere center sphere_emitter->set_amplitude(1); sphere_emitter->set_amplitude_spread(0); sphere_emitter->set_offset_force(LVector3f(0, 0, 0)); sphere_emitter->set_explicit_launch_vector(LVector3f(1, 0, 0)); sphere_emitter->set_radiate_origin(LPoint3f(0, 0, 0)); Renderer: ========= The renderer is used to specify how the particle appears on screen. Available renderers: ==================== - GeomParticleRenderer: displays each particle on the shape of a selected PandaNode - LineParticleRenderer: displays each particle as a line - PointParticleRenderer: displays each particle as a point - SparkleParticleRenderer displayes each particle as a plus (+) - SpriteParticleRenderer:  displays each particle as a sprite Each renderer is declared in a separate .h file with the same name as the renderer. For example: GeomParticleRenderer is declared in geomParticleRenderer.h [Sample] .. code-block:: cpp PT(PointParticleRenderer) pt_particle_rend = new PointParticleRenderer(); pt_particle_rend->set_alpha_mode(BaseParticleRenderer::PR_ALPHA_OUT); pt_particle_rend->set_user_alpha(1); pt_particle_rend->set_point_size(2.0); pt_particle_rend->set_start_color(Colorf(1, 0, 0, 1)); // alpha value is ignored pt_particle_rend->set_end_color(Colorf(1, 1, 0, 1)); pt_particle_rend->set_blend_type(PointParticleRenderer::PointParticleBlendType::PP_BLEND_LIFE); pt_particle_rend->set_blend_method(BaseParticleRenderer::ParticleRendererBlendMethod::PP_BLEND_LINEAR); //pt_particle_rend->set_color_blend_mode(ColorBlendAttrib::Mode::M_inv_subtract); //pt_particle_rend->set_ignore_scale(false); ParticleSystem: =============== This class is the controller of the particle system.  The main parameters are: - Pool Size: the maximum number of particles the factory can generate Birth Rate: number of seconds between particle births, also it is the time after which the first birth occurs. So if the value is 6 the first litter will be born after 6 seconds. - Litter Size: number of particles created at each birth. If you want all the particles to be born at the same time, set this value to the value of (Pool Size) Litter Spread: this adds a random value in the range [-spread, +spread] to the value of Litter Size. - Lifespan:  number of seconds the system will live. - System Grows Older: this flag must be set for the Lifespan value to be used. It's very important to remember that particle systems which reach the end of their lifespan are automatically removed from the ParticleSystemManager and if you want to reuse them, they should be added to the ParticleSystemManager again. [Sample] .. code-block:: cpp PT(ParticleSystem) particle_sys = new ParticleSystem(); particle_sys->set_pool_size(100); particle_sys->set_birth_rate(0.1); particle_sys->set_litter_size(10); particle_sys->set_litter_spread(0); particle_sys->set_local_velocity_flag(true); //particle_sys->set_spawn_on_death_flag(true); // this caused an exception!! particle_sys->set_system_grows_older_flag(true); particle_sys->set_system_lifespan(3.0); particle_sys->set_active_system_flag(true); // use it to advance system age, or start at some age //particle_sys->set_system_age(5.0); // system_age is updated only when set_system_grows_older_flag(true); // get_system_age() returns 0 unless system_grows_older_flag is set The particle factory, emitter and renderer should be attached to the ParticleSystem and most important the render node should be set. .. code-block:: cpp particle_sys->set_factory(pt_particle_factory); particle_sys->set_renderer(pt_particle_rend); particle_sys->set_emitter(sphere_emitter); // if spawn and render parents should be different //particle_sys->set_spawn_render_node_path(window->get_render()); particle_sys->set_render_parent(window->get_render()); ParticleSystemManager: ====================== This class is responsible for simplifying control of particle systems. Instead of stepping each particle system in the scene they are all added to the ParticleSystemManager and they can be all stepped using a single command or they can be stepped individually. This class is not count referenced so PT() and CPT() should not be used with it. To attach a particle system to the manager: .. code-block:: cpp particle_sys_mgr.attach_particlesystem(particle_sys); To step all the particle systems: .. code-block:: cpp particle_sys_mgr.do_particles(ClockObject::get_global_clock()->get_dt()); To step a specific particle system: .. code-block:: cpp particle_sys_mgr.do_particles(ClockObject::get_global_clock()->get_dt(), particle_sys); NOTE: particle systems which reach the end of their lifespan are automatically removed from the ParticleSystemManager and if you want to reuse them, they should be added to the ParticleSystemManager again.